/**
 *  Copyright (C) 2010:
 *                 Buzzanca Marco <marco.bzn@gmail.com>
 *         Monaco Davide Giuseppe <black.ralkass@gmail.com>
 *              Petralia Veronica <veronicapetralia@gmail.com>
 *
 * This file is part of DS2011BMP
 *
 * DS2011BMP is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * DS2011BMP is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

/**
 * @file ui.h
 * @author Davide Giuseppe Monaco
 * @author Marco Buzzanca
 *
 * This header file contains UI class declaration.
 */

#ifndef _UI_H_
#define _UI_H_ 1

#include <boost/cstdint.hpp>
#include <boost/thread.hpp>

#include "synque.h"
#include "taskdescriptor.h"
#include "udpserver.h"
#include "wfqproxyfactory.h"
#include "wfqueuemanagerproxy.h"
#include "workflow.h"

/**
 * @brief User interface class.
 *
 * Through WFQProxyFactory obtains a WFQueueManagerProxy in order to
 * communicate with WFQueueManager via UDP sockets.
 * UI-Manager communication consists in enqueue() calls to add new Workflow(s)
 * to Manager queue.
 *
 * In addition, after a TaskDescriptor has been delivered to a Worker, 
 * the UI listens for UDP file transfer requests advanced by them in order to
 * provide the file specified in TaskDescriptor::_link member.
 */
class UI
{
private:
    typedef struct
    {
        boost::shared_ptr<char> source_file;
        std::string client_IP;
        std::string client_port;

    } _ft_req;

    /**
    * @brief WFQProxyFactory.
    */
    WFQProxyFactory _wfqp_factory;

    /**
    * @brief Manager Address.
    */
    Address _manager_address;

    /**
     * @brief Port used to accept incoming connections.
     */
    boost::uint16_t _port;

    /**
     * @brief Provides basic I/O services.
     */
    boost::asio::io_service _io_service;

    /**
     * @brief The queue used to send files specified in 
     * TaskDescriptor::_link member for each TaskDescriptor in a submitted
     * Workflow.
     */
    synque<_ft_req> _file_requests;

    /**
     * @author Marco Buzzanca
     *
     * @brief UI thread called by server thread callback member function,
     *        used to process a request.
     */
    void sendFile(void);

    /**
     * @author Marco Buzzanca
     *
     * @brief Generates workflow which submits to manager node.
     */
    void generateWorkflow(void);

public:
    /**
    * @brief Default Constructor. Uses default port value (11000);
    */
    UI(void);

    /**
    * @brief Constructor from specified manager address. Uses default port
    *        value for server (11000).
    *
    * @param manager_address Manager address.
    */
    UI(const Address& manager_address);

    /**
    * @brief Constructor from specified manager address, and local server
    *        address object.
    *
    * @param manager_address Manager Address.
    * @param address Local server address.
    *
    * @note It completely ignores IP data of server_address, only port is
    *       needed.
    */
    UI(const Address& manager_address, const Address& address);

    /**
    * @brief Constructor from specified manager node address and port, and
    *        local server port.
    *
    * Default port value is 11000.
    */
    UI(const std::string& manager_IP, boost::uint16_t manager_port,
       boost::uint16_t server_port = 11000);

    /**
    * @brief Destructor.
    */
    ~UI(void);

    /**
    * @brief Gets manager address.
    * @return Manager's address.
    */
    const Address& getManagerAddress() const;

    /**
    * @brief Sets manager address using provided Address.
    * @param manager_address The provided Address.
    */
    void setManagerAddress(const Address& manager_address);

    /**
    * @brief Sets manager address using provided IP and port.
    * @param manager_IP The provided manager IP address.
    * @param manager_port The provided manager port.
    */
    void setManagerAddress(const std::string& manager_IP,
                           boost::uint16_t manager_port);

    /**
    * @brief Gets server port.
    * @return Server port.
    */
    boost::uint16_t getServerPort() const;

    /**
    * @brief Sets server port to the provided one.
    * @panam server_port The provided port.
    */
    void setServerPort(boost::uint16_t server_port);

    /**
    * @brief UI behaviour in the application.
    */
    void run(void);
};

#endif /* _UI_H_ */
